home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
raytrace
/
pov
/
gen
/
pvcoil21
/
coil.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-17
|
19KB
|
488 lines
/*
Program : Coil v2.0
Purpose : Create coil objects for PoV Ray v1.0 raytracer
Created : 7/25/92
By : Bill Kirby CIS [70711,2407]
File : COIL.C
Compiler: Borland C++ v3.1
Model : Small
Comments: Creates twisted coil object made with spheres.
*/
/*
Program : Coil v2.10b
Purpose : Create coil objects for PoV Ray v1.0 and Polyray v1.6 raytracers
and also export to CTDS and WORM file formats.
Created : 9/14/93
By : Rob Bryerton CIS [73747,433]... based on original C code
by Bill Kirby
File : COIL.CPP
Compiler: Microsoft C++ v8.00
Model : Small
Comments: Creates twisted coil object made with spheres or other shapes
*/
#include <fstream.h>
#include <math.h>
#include <stdio.h> // for getchar()
#include <stdlib.h>
#include <string.h>
#include <graph.h> // for graphics
ofstream outfile;
const int BUFFSIZE = 256;
enum Format {POV,POLY,CTDS,WORM};
enum bool {FALSE,TRUE};
enum Shape {Sphere,Ellipsoid,Box,Cone,Y_Cylinder};
char buff[BUFFSIZE];
const double PI = 3.1415926535897932384626;
/*
#ifndef PI
#define PI 3.1415926535897932384626
#endif*/
void err_exit(char *message);
void usage(void);
class Base_Obj
{
protected:
double x_1,y_1,x_2,z_2,xpos,ypos,zpos,Rad1,rad2,radius,angle1,angle2,k;
double xpos_1,ypos_1; // for graphics... remembers 1st graphics points
long Ntwist,Ntube,counter,steps,shape_type;
char com[3],union_name[80];
bool extended, display;
Format format;
Shape shape;
int v_mode;
public:
char filename[80];
Base_Obj(){ // no arg constructor
xpos=0.0; ypos=0.0; zpos=0.0; radius=0.25;strcpy(com,"//");
extended=FALSE;display = FALSE; format=POV; counter=0;shape=Sphere;
outfile.setf(ios::showpoint | ios::fixed);outfile.precision(6); }
virtual void do_calc(void);
virtual void get_inputs(void);
void init_display(void);
void close_display(void);
void draw_piece(void);
void process_args(int argc, char* argv[]);
void process_option(char *s);
void set_precision(char *prec);
void show_title(void);
virtual void write_end(void){};
virtual void write_header(void);
virtual bool write_piece(void){if(display) draw_piece(); // draw current line
return (counter < steps) ? TRUE:FALSE; }
};
class POV_Obj:public Base_Obj
{
private:
double xmax,xmin,ymax,ymin,zmax,zmin;
public:
POV_Obj(){
xmax=0.0,xmin=0.0,ymax=0.0, // no arg constructor
ymin=0.0,zmax=0.0,zmin=0.0;}
void do_calc(void);
void get_inputs(void);
void write_header(void);
bool write_piece(void);
void write_end(void);
};
class POLY_Obj:public Base_Obj
{
public:
POLY_Obj(){format=POLY;}
void get_inputs(void);
void write_header(void);
bool write_piece(void);
void write_end(void);
};
class CTDS_Obj:public Base_Obj // ********** full definition of class
{
public:
CTDS_Obj() {format=CTDS; strcpy(com,";"); strcpy(union_name,"-----");}
bool write_piece(void)
{
outfile << xpos << " " << ypos << " " << zpos << " "
<< radius << endl;
Base_Obj::write_piece();
return ((counter < steps) ? TRUE:FALSE);
}
void write_end(void){};
};
class WORM_Obj:public Base_Obj // ********** full definition of class
{
public:
WORM_Obj(){format=WORM;}
void write_header(void)
{ outfile << steps << endl; }
bool write_piece(void)
{
outfile << xpos << ", " << ypos << ", " << zpos << ", "
<< radius <<", " << (counter==1?0:1) << endl;
Base_Obj::write_piece();
return ((counter < steps) ? TRUE:FALSE);}
void write_end(void){};
};
//main
int main(int argc, char* argv[])
{
int choice = 1;
Base_Obj* coil_ptr; // pointer to class Base_Obj
Base_Obj vec; // object of " " " "
coil_ptr = &vec;
if(argc > 1) coil_ptr->process_args (argc, argv); // check for validity
coil_ptr->show_title();
cout<< "1\tPOV\n2\tPolyray\n3\tCTDS\n4\tWORM\n" << "Number for format? [1]: ";
cin.getline(buff,BUFFSIZE); choice = atoi(buff); // output format
switch(choice){ // construct appropriate object based on above choice
case 2: {POLY_Obj vec2; coil_ptr = &vec2;} break;
case 3: {CTDS_Obj vec3; coil_ptr = &vec3;} break;
case 4: {WORM_Obj vec4; coil_ptr = &vec4;} break;
default:{POV_Obj vec1; coil_ptr = &vec1;} }
if(argc > 1) coil_ptr->process_args (argc, argv); // set options
coil_ptr->get_inputs(); // get parameters from user
outfile.open(coil_ptr->filename,ios::out); // try to open disk file
if(! outfile) err_exit("Opening file."); // if disk access error,exit
coil_ptr->write_header(); // success, make a coil
coil_ptr->init_display(); // set up display if desired
cerr<< "\nCreating data file " << coil_ptr->filename << endl;
do coil_ptr->do_calc(); // calculate current vector
while(coil_ptr->write_piece()); // write current line to disk
coil_ptr->write_end(); // write texture block (POV or Polyray only)
outfile.close; // close disk file
coil_ptr->close_display(); // exit graphics mode if applicable
cout << "\nFile " << coil_ptr->filename <<" created.\n";
return(0);
}
void err_exit(char *message)
{
cerr << "\n\nERROR! \a" << message << "... Exiting \n";
exit(1);
}
void usage()
{
cerr << "\n--------------------------------Coil v2.10--------------------------------------"
<< "Usage: coil [options]\n"
<< "Options: -d# enables 2D (xy) display of coil... # is the graphics mode\n"
<< " 1=640x480 2=800x600 3=1024x768 (default # value is 1)\n\n"
<< " -e gives you an extended menu with a choice of objects \n"
<< " (cone, cylinder, box, etc.) for POV-Ray or Polyray output.\n\n"
<< " -p# where # is the precision of the output file numbers.\n"
<< " Range is 2 - 9 with a default precision of 6 decimal places.\n"
<< "\nType COIL with no parameters for the default menus and options.\n"
<< "--------------------------------------------------------------------------------";
}
// ************* Base and Derived Class function definitions**************
// ************* Base Class Base_Obj function definitions **************
void Base_Obj::close_display()
{
if(display){
cerr << "\nPress return.";
getchar();
_setvideomode(_DEFAULTMODE);}
}
void Base_Obj::do_calc()
{
angle1 = 2 * PI * Ntube * (double)counter / (double)steps;
x_1 = cos( angle1 );y_1 = sin( angle1 );
angle2 = (double)( Ntwist + 1.0/Ntube) * angle1;
x_2 = cos( angle2 );z_2 = sin( angle2);
xpos = k * ((Rad1 * x_1) + (rad2 * x_2 * x_1));
ypos = k * ((Rad1 * y_1) + (rad2 * x_2 * y_1));
zpos = k * rad2 * z_2; counter++;
}
void Base_Obj::draw_piece()
{
struct _videoconfig vc;
_getvideoconfig( &vc );
_setcolor (12); /* brt red */
double rads = Rad1+rad2;
int vidx = int((xpos*(vc.numxpixels*0.33)/k)/rads+(0.5*vc.numxpixels));
int vidy = int((ypos*(vc.numxpixels*0.33)/k)/rads+(0.5*vc.numypixels));
if(counter==1){ _moveto (vidx, vidy); xpos_1=vidx; ypos_1=vidy; }
if(counter<=steps){ _lineto (vidx,vidy); _setcolor (10); /* brt grn */
int elip_x1 = (vidx-(radius*(0.28*vc.numypixels/k)));
int elip_y1 = (vidy-(radius*(0.28*vc.numypixels/k)));
int elip_x2 = (vidx+(radius*(0.28*vc.numypixels/k)));
int elip_y2 = (vidy+(radius*(0.28*vc.numypixels/k)));
//_ellipse( _GBORDER, vidx-(radius*(0.28*vc.numxpixels)),vidy-(radius*(0.28*vc.numxpixels)),vidx+(radius*(0.28*vc.numxpixels)),vidy+(radius*(0.28*vc.numxpixels))); }
_ellipse( _GBORDER, elip_x1, elip_y1, elip_x2, elip_y2); }
if(counter==steps){ _setcolor (12); _lineto (xpos_1,ypos_1); }
}
void Base_Obj::get_inputs()
{
cout << "Ouput filename? [coil.inc]: ";
cin.getline(buff,BUFFSIZE); strcpy(filename,buff);
if(format < CTDS){
cout << "Union name? [coil]: ";
cin.getline(buff,BUFFSIZE); strcpy(union_name,buff);}
cout << "Number of objects? [100]: ";
cin.getline(buff,BUFFSIZE); steps = atoi(buff);
cout << "Number of objects in cross-section? [2]: ";
cin.getline(buff,BUFFSIZE); Ntube = atoi(buff);
cout << "Number of twists per revolution? [2]: ";
cin.getline(buff,BUFFSIZE); Ntwist = atoi(buff);
cout << "Major radius? [1.0]: ";
cin.getline(buff,BUFFSIZE); Rad1 = atof(buff);
cout << "Minor radius? [0.25]: ";
cin.getline(buff,BUFFSIZE); rad2 = atof(buff);
cout << "Object 'radius'? [0.25]: ";
cin.getline(buff,BUFFSIZE); radius = atof(buff);
cout << "Overall scale value (k)? [1.0]: ";
cin.getline(buff,BUFFSIZE); k = atof(buff);
// Set up default values
if(filename[0]=='\0') strcpy(filename,"coil.inc");
if(union_name[0]=='\0') strcpy(union_name,"coil");
if(steps==0) steps = 100; if(Ntube==0) Ntube = 2;
if(Ntwist==0) Ntwist = 2; if(Rad1==0.0) Rad1 = 1.0;
if(rad2==0.0) rad2 = 0.25; if(radius==0.0) radius = 0.25;
if(k==0.0) k = 1.0; if(shape_type==0) shape_type = 1;
switch(shape_type){
case 2 : shape = Ellipsoid; break;
case 3 : shape = Box; break;
case 4 : shape = Cone; break;
case 5 : shape = Y_Cylinder; break;
default: shape = Sphere;
}
}
void Base_Obj::init_display()
{ if(display){
switch(v_mode){
case 3 : if(!_setvideomode(_XRES16COLOR)) cerr << "\nCouldn't set graphics mode... continuing\n";
break; /* 1024x768x16 */
case 2 : if(!_setvideomode(_SRES16COLOR)) cerr << "\nCouldn't set graphics mode... continuing\n";
break; /* 800x600x16 */
default : if(!_setvideomode(_VRES16COLOR)) cerr << "\nCouldn't set graphics mode... continuing\n";
} /* 640x480x16 */
}
}
void Base_Obj::process_args (int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
if (argv[i][0] == '-' || argv[i][0] == '/')
process_option (&argv[i][1]);
else
{usage(); err_exit("Invalid option");}
}
}
void Base_Obj::process_option (char *s)
{
switch (toupper(s[0]))
{
case 'E': extended = TRUE; break;
case 'P': set_precision(&s[1]); break;
case 'D': display = TRUE; v_mode = atoi(&s[1]); break;
case '?': usage(); exit(0);
case 'H': usage(); exit(0);
default : usage(); err_exit("Invalid option");
}
}
void Base_Obj::set_precision(char *prec)
{
outfile.precision((atoi(prec) > 1 ? atoi(prec) : 6 ));
}
void Base_Obj::show_title()
{
cout << "Coil v2.10\n"
<< "Creates a data file of a twisted coil object for the PoV-Ray v1.0" << endl
<< "and Polyray v1.6 raytracers, Connect The Dots Smoother (CTDS), and WORM.\n"
<< "- v2.0 C source by W. D. Kirby 7/25/92\n"
<< "- v2.1 C++ update by R. Bryerton 9/14/93\n\n";
}
void Base_Obj::write_header()
{
outfile
<<com<<" File: "<<filename<<" Union Name: "<<union_name<< endl
<<com<<" This data file created by COIL.EXE v2.10 for the PoV Ray v1.0 and\n"
<<com<<" Polyray v1.6 raytracers, Connect The Dots Smoother (CTDS), and WORM.\n\n"
<<com<<" Twists="<<Ntwist<<" Cross Section="<<Ntube<<" Objects="<<steps<<" Scale=" << k << "\n\n";
}
// *************************** Derived Class POV_Obj function definitions
void POV_Obj::get_inputs()
{
if(extended){
cout << "\n1\tSphere\n2\tEllipsoid\n3\tBox\n4\tCone\n5\tY_Cylinder\n";
cout << "Shape type? [1]: ";
cin.getline(buff,BUFFSIZE); shape_type = atoi(buff); }
Base_Obj::get_inputs(); // call base class function
}
void POV_Obj::do_calc()
{
Base_Obj::do_calc(); //call base class function 1st
xmax = __max(xmax,xpos);xmin = __min(xmin,xpos); // calculate bounds
ymax = __max(ymax,ypos);ymin = __min(ymin,ypos); // (POV only)
zmax = __max(zmax,zpos);zmin = __min(zmin,zpos);
}
void POV_Obj::write_header()
{
Base_Obj::write_header(); // call base class function first
if(shape > Sphere){
outfile << "// You MUST #declare shapes.inc in either this file or your .POV file...\n\n"
<< "#declare object_scale = <" << 0.5*radius << " "<< 0.5*radius << " "<< 0.5*radius << ">"<< endl
<< "#declare object_rotate = <0 0 0>" << endl
<< "// Change object_scale and object_rotate to modify EVERY object\n\n";
}
outfile << "declare "<<union_name<<" = object {\n union {\n";
}
bool POV_Obj::write_piece()
{
switch(shape){
case Ellipsoid : outfile << " quadric { Ellipsoid scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n"; break;
case Box : outfile << " box { UnitBox scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n"; break;
case Cone : outfile << " intersection { Cone_Y scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n"; break;
case Y_Cylinder : outfile << " intersection { Disk_Y scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n"; break;
default : outfile << " sphere { < "<<xpos<<" "<<ypos<<" "<<zpos<<" > "<<radius<<" }\n";}
Base_Obj::write_piece(); return (counter < steps) ? TRUE:FALSE;
}
void POV_Obj::write_end()
{ // calculate bounding box
xmax = 1.01 * (xmax + radius); xmin = 1.01 * (xmin - radius);
ymax = 1.01 * (ymax + radius); ymin = 1.01 * (ymin - radius);
zmax = 1.01 * (zmax + radius); zmin = 1.01 * (zmin - radius);
outfile << " }\n\n"
<< "bounded_by {\n"
<< " box { < " << xmin<<" "<<ymin<<" "<<zmin << "> < "
<< xmax<<" "<<ymax<<" "<<zmax << "> }\n }\n"
<< " texture {\n"
<< " ambient 0.3\n"
<< " diffuse 0.7\n"
<< " phong 1.0\n"
<< " phong_size 20.0\n"
<< " color red 1.0 green 0.0 blue 0.0\n"
<< " }\n\n}\n\n";
}
// *************************** Derived Class POLY_Obj function definitions
void POLY_Obj::get_inputs()
{
if(extended){
cout << "\n1\tSphere\n2\tEllipsoid\n3\tBox\n4\tCone\n5\tY_Cylinder\n\n";
cout << "Shape type? [1]: ";
cin.getline(buff,BUFFSIZE); shape_type = atoi(buff);}
Base_Obj::get_inputs(); // call base class function
}
void POLY_Obj::write_header()
{
Base_Obj::write_header(); // call base class function first
if(shape > Sphere) outfile << "define object_scale <" << 0.5*radius << ", " << 0.5*radius << ", " << 0.5*radius << ">\n"
<< "define object_rotate <0, 0, 0>\n"
<<"// Change object_scale and object_rotate to modify EVERY object\n\n";
switch(shape){ // cap the cone and cylinder to be consistent w/POV
case Ellipsoid : outfile << "define Ellipsoid object{ sphere<0,0,0>,1 scale object_scale rotate object_rotate}\n"; break;
case Box : outfile << "define UnitBox object{ box<-1,-1,-1>,<1,1,1> scale object_scale rotate object_rotate}\n";break;
case Cone : outfile << "define Y_Cone object{\n object{cone<0,-1,0>,1,<0,1,0>,0 scale object_scale rotate object_rotate}+\n"
<< " object {disc <0, -1, 0>, <0, 1, 0>, 1 scale object_scale rotate object_rotate}\n}\n";break;
case Y_Cylinder: outfile << "define Y_Cylinder object{\n object{cylinder<0,-1,0>,<0,1,0>,1 scale object_scale rotate object_rotate}+\n"
<< " object {disc <0, 1, 0>, <0, 1, 0>, 1 scale object_scale rotate object_rotate}+\n"
<< " object {disc <0, -1, 0>, <0, 1, 0>, 1 scale object_scale rotate object_rotate}\n}\n";break;
default : break; }
outfile << "\ndefine "<<union_name<<"\n object {\n";
}
bool POLY_Obj::write_piece()
{
switch(shape){
case Ellipsoid : outfile << " Ellipsoid{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
case Box : outfile << " UnitBox{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
case Cone : outfile << " Y_Cone{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
case Y_Cylinder: outfile << " Y_Cylinder{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
default : outfile << " object { sphere < "<<xpos<<", "<<ypos<<", "<<zpos<<" >, "<<radius<<" } ";}
if (counter < steps) // for all obects EXCEPT the last
outfile << "+\n";
else // for last object only (no "+")
outfile << endl;
Base_Obj::write_piece(); return (counter < steps) ? TRUE:FALSE;
}
void POLY_Obj::write_end()
{
outfile << " texture {\n"
<< " surface {\n"
<< " ambient red, 0.275\n"
<< " diffuse red, 0.8\n"
<< " specular white, 1.0\n"
<< " microfacet Phong 7\n }\n"
<< " }\n\n}\n\n";
}